home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
ZED3DSRC.ZIP
/
XFORMS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-19
|
8KB
|
446 lines
#include <xforms.h>
#include <stdio.h>
/* if your compiler supports some form of function inlining, you can try
removing the comment below (doubt it will work though) */
/* For the two next functions, in a real program they would probably
be implemented as macros for more speed */
fixedpoint fixed_mul(fixedpoint a, fixedpoint b)
{
#ifdef __TURBOC__
#pragma inline
/* Note:
The following asm code is very fast for a PC. Ideally, you should
make it so that you use this code instead of the code after the
#else (of course, ideally it should be inlined...) */
long c;
asm{
mov eax,a /*first operand*/
mov edx,b /*second operand*/
imul edx /*multiply them*/
shl edx,16 /* put integer value in upper 16 bits*/
shr eax,16 /* truncate fraction part*/
or eax,edx /* fuse integer and fractional part*/
mov c,eax
}
return c;
#else
return ((a/256)*(b/256)); /* a poor patch*/
#endif
}
fixedpoint fixed_div(fixedpoint a, fixedpoint b)
{
#ifdef __TURBOC__
/* Note:
The following asm code is very fast for a PC. Ideally, you should
make it so that you use this code instead of the code after the
#else (of course, ideally it should be inlined...) */
long c;
asm{
mov edx,a /*load a in edx:eax, 64 bits*/
mov eax,edx
sar edx,16
shl eax,16
mov ecx,b /* load b in ecx*/
idiv ecx /* divide edx:eax by ecx*/
mov c,eax
}
return c;
#else
return ((a*256)/(b/256)); /* poor patch*/
#endif
}
void mat_add(matrix r, matrix a, matrix b)
{
int x,y;
for(x=0;x<3;x++)
for(y=0;y<3;y++)
r[x][y]=add(a[x][y],b[x][y]);
}
void mat_sub(matrix r, matrix a, matrix b)
{
int x,y;
for(x=0;x<3;x++)
for(y=0;y<3;y++)
r[x][y]=sub(a[x][y],b[x][y]);
}
void mat_mul(matrix r, matrix a, matrix b)
{
int x,y,z;
for(x=0;x<3;x++)
for(y=0;y<3;y++)
{
r[y][x]=floattoreal(0.0);
for(z=0;z<3;z++)
r[y][x]=add(r[y][x],mul(a[z][x],b[y][z]));
}
}
void mat_mul_vec(vector r, matrix a, vector b)
{
int x,y;
for(x=0;x<3;x++)
{
r[x]=floattoreal(0.0);
for(y=0;y<3;y++)
r[x]=add(r[x],mul(a[y][x],b[y]));
}
}
void vec_add(vector r, vector a, vector b)
{
int x;
for(x=0;x<3;x++)
r[x]=add(a[x],b[x]);
}
void vec_sub(vector r, vector a, vector b)
{
int x;
for(x=0;x<3;x++)
r[x]=sub(a[x],b[x]);
}
REAL vec_dot(vector a, vector b)
{
/* a dot b is a[0]*b[0]+a[1]*b[1]+a[2]*b[2] */
REAL dot;
int x;
dot=floattoreal(0.0);
for(x=0;x<3;x++)
dot=add(dot,mul(a[x],b[x]));
return dot;
}
void vec_normalize(vector a)
{
REAL length;
int x;
/* first use find euclidian length of vector. It is the square root
of the sum of the square of the vector components. E.g. in 2d, this
simplifies to pythagora's theorem, a^2+b^2=c^2. In 3d, it's
a^2+b^2+c^2=d^2 */
#ifdef use_fixed
do {
#endif
length=floattoreal(0.0);
for(x=0;x<3;x++)
length=add(length,mul(a[x],a[x])); /* calculate sum */
length=SQRT(length); /* extract square root */
#ifdef use_fixed
if(length<=floattoreal(0.001))
vec_mul_scl(a,a,floattoreal(1000));
} while(length<=floattoreal(0.001));
#endif
/* second divide each component of the vector by the length of the
vector */
for(x=0;x<3;x++)
a[x]=div(a[x],length);
}
void vec_mul_scl(vector r, vector a, REAL b)
{
int x;
for(x=0;x<3;x++)
r[x]=mul(a[x],b);
}
void vec_crs(vector r, vector a, vector b)
{
/* (a0,a1,a2) cross (b0,b1,b2) is
(a1b2-a2b1 , a2b0,a0b2 , a0b1-a1b0) */
r[0]=sub(mul(a[1],b[2]),mul(a[2],b[1]));
r[1]=sub(mul(a[2],b[0]),mul(a[0],b[2]));
r[2]=sub(mul(a[0],b[1]),mul(a[1],b[0]));
}
void mat_orthonormalize(matrix a)
{
vector temp;
/* normalize first vector */
vec_normalize(a[0]);
/* make second vector perpendicular to the first */
vec_mul_scl(temp,
a[0],
vec_dot(a[1],a[0])
);
vec_sub(a[1],
a[1],
temp
);
/* normalize second vector */
vec_normalize(a[1]);
/* third vector is first cross second */
vec_crs(a[2],a[0],a[1]);
/* no need to normalize this third one since the first two are
normalized*/
}
#define z(x,y) m[x][y]=floattoreal(a##y##x)
void initmatrix(matrix m,
float a00, float a01, float a02,
float a10, float a11, float a12,
float a20, float a21, float a22)
{
z(0,0);
z(0,1);
z(0,2);
z(1,0);
z(1,1);
z(1,2);
z(2,0);
z(2,1);
z(2,2);
}
void printmatrix(matrix m)
{
int x;
for(x=0;x<3;x++)
{
printf("\n%13.5f %13.5f %13.5f",
realtofloat(m[0][x]),
realtofloat(m[1][x]),
realtofloat(m[2][x])
);
}
printf("\n");
}
void initvector(vector v,
float i, float j, float k)
{
v[0]=i;
v[1]=j;
v[2]=k;
}
void printvector(vector v)
{
printf("\n(%f,%f,%f)\n",
realtofloat(v[0]),
realtofloat(v[1]),
realtofloat(v[2]));
}
void copymatrix(matrix dest, matrix src)
{
copyvector(dest[0],src[0]);
copyvector(dest[1],src[1]);
copyvector(dest[2],src[2]);
}
void copyvector(vector dest, vector src)
{
dest[0]=src[0];
dest[1]=src[1];
dest[2]=src[2];
}
void rotatevectors(vector v1, vector v2,
vector u1, vector u2,
REAL theta)
{
REAL s,c; /* sintheta and costheta respectively */
vector t1,t2,g1,g2;
s=SIN(theta);
c=COS(theta);
/* formula is: u1=v1costheta-v2sintheta
u2=v1sintheta+v2costheta */
vec_mul_scl(t1,v1,c);
vec_mul_scl(t2,v2,s);
vec_mul_scl(g1,v1,s);
vec_mul_scl(g2,v2,c);
vec_sub(u1,t1,t2);
vec_add(u2,g1,g2);
}
void rotatebase(matrix m, int axis, REAL theta)
{
int a,b;
a=axis+1;
if(a>=3)
a-=3;
b=a+1;
if(b>=3)
b-=3;
rotatevectors(m[a],m[b],m[a],m[b],theta);
}
REAL determinant(matrix m)
{
/* det m is:
m[0][0]*m[1][1]*m[2][2]+
m[0][1]*m[1][2]*m[2][0]+
m[0][2]*m[1][0]*m[2][1]
-
m[0][0]*m[1][2]*m[2][1]-
m[0][1]*m[1][0]*m[2][2]-
m[0][2]*m[1][1]*m[2][0]
*/
return
mul(mul(m[0][0],m[1][1]),m[2][2])+
mul(mul(m[0][1],m[1][2]),m[2][0])+
mul(mul(m[0][2],m[1][0]),m[2][1])
-
mul(mul(m[0][0],m[1][2]),m[2][1])-
mul(mul(m[0][1],m[1][0]),m[2][2])-
mul(mul(m[0][2],m[1][1]),m[2][0]);
}
void mat_mul_scl(matrix r, matrix a, REAL b)
{
int x,y;
for(x=0;x<3;x++)
for(y=0;y<3;y++)
r[x][y]=mul(a[x][y],b);
}
int invert(matrix m, matrix r)
{
/* inverse matrix is cofactors matrix divided by determinant if
determinant is nonzero. so first calculate determinant, if
zero return error. then calculate cofactor matrix and divide by
determinant */
matrix cof;
REAL det;
det=determinant(m);
if(!det)
{
return -1; /* error, matrix inverse does not exist */
}
/* matrix of cofactors is hard wired here for 3x3 matrices */
initmatrix(r,
mul(m[1][1],m[2][2])-mul(m[1][2],m[2][1]),
mul(m[2][0],m[1][2])-mul(m[1][0],m[2][2]),
mul(m[1][0],m[2][1])-mul(m[2][0],m[1][1]),
mul(m[2][1],m[0][2])-mul(m[0][1],m[2][2]),
mul(m[0][0],m[2][2])-mul(m[0][2],m[2][0]),
mul(m[2][0],m[0][1])-mul(m[0][0],m[2][1]),
mul(m[0][1],m[1][2])-mul(m[1][1],m[0][2]),
mul(m[1][0],m[0][2])-mul(m[0][0],m[1][2]),
mul(m[0][0],m[1][1])-mul(m[1][0],m[0][1]));
/* now we have matrix of cofactors. multiply it by 1/det */
det=div(floattoreal(1.0),det);
mat_mul_scl(r,r,det);
/* return success */
return 0;
}
int invert_affine(affine *a, affine *r)
{
if(invert(a->m,r->m))
return -1;
mat_mul_vec(r->v,a->m,a->v);
r->v[0]=-r->v[0];
r->v[1]=-r->v[1];
r->v[2]=-r->v[2];
return 0;
}
void affine_xform(affine *a, vector i, vector j)
{
mat_mul_vec(j,a->m,i);
vec_add(j,j,a->v);
}